package api

import (
	dao2 "TaskAssignmentSystem/internal/admin/dao"
	services2 "TaskAssignmentSystem/internal/admin/services"
	"TaskAssignmentSystem/internal/app/dao"
	"TaskAssignmentSystem/internal/app/services"
	"TaskAssignmentSystem/internal/pkg/middleware/handler"
	"TaskAssignmentSystem/internal/pkg/modelbase"
	Redis "TaskAssignmentSystem/pkg/db/redis"
	"TaskAssignmentSystem/pkg/utils"
	"encoding/json"
	"fmt"
	"github.com/golang/glog"
	"github.com/kataras/iris/v12"
	"github.com/wxnacy/wgo/arrays"
	"gorm.io/gorm"
	"strings"
	"time"
)

type ProjectsRequest struct {
	Page                     int64  `json:"page"`
	PageSize                 int64  `json:"page_size"`
	SearchText               string `json:"search_text"`
	Category                 string `json:"category"`
	SpecialClassificationOne string `json:"special_classification_one"` //特殊分类1(0-关闭,1-开启)
	SpecialClassificationTwo string `json:"special_classification_two"` //特殊分类2(0-关闭,1-开启)
	Collect                  string `json:"collect"`                    //收藏
}

// @Summary 项目列表
// @Description 项目列表
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param param body ProjectsRequest true "项目列表参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /app/project/list [post]
func ProjectsHandler(ctx iris.Context) {
	var RequestParams ProjectsRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}

	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	/*
		判断用户所属团队，是否控制显示权限
		   是：只显示团队项目，return
		   否：查询项目可见性，遍历用户权限，没权限显示未开通
	*/
	var common dao.Common[dao.SystemUser]
	common.Query = map[string]interface{}{"id": claims.Id}
	user, err := common.First(common.Query)
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}

	projectType := "noTeam"
	var userProjects []string
	//查询团队表，如果团长设置了只允许查看团队项目，则只查看团队项目
	var teamDao dao2.Common[dao2.SystemTeam]
	//用户是团长则直接查团队配置
	if teamInfo, err := teamDao.First(map[string]interface{}{"user_id": claims.UserName, "status": 1}); err == nil {
		if utils.StringIsNotEmpty(teamInfo.TeamPermissions) {
			projectIds := strings.Split(teamInfo.TeamPermissions, "，")
			for _, id := range projectIds {
				userProjects = append(userProjects, id)
				projectType = "team"
			}
		} else {
			//团队配置没查到也读用户自己配置
			for _, u := range user.SystemUserRestriction {
				userProjects = append(userProjects, u.ProjectId)
			}
		}
	} else {
		//用户是团队也查询团队配置
		if utils.StringIsNotEmpty(user.TeamNumber) && user.TeamNumber != "zxz" {
			if teamInfo2, err := teamDao.First(map[string]interface{}{"team_number": user.TeamNumber, "status": 1}); err == nil {
				if utils.StringIsNotEmpty(teamInfo2.TeamPermissions) {
					projectIds := strings.Split(teamInfo2.TeamPermissions, "，")
					for _, id := range projectIds {
						userProjects = append(userProjects, id)
					}
					projectType = "team"
				} else {
					//团队没配置则读用户自己配置
					for _, u := range user.SystemUserRestriction {
						userProjects = append(userProjects, u.ProjectId)
					}
				}
			} else {
				//团队没查到也读用户自己配置
				for _, u := range user.SystemUserRestriction {
					userProjects = append(userProjects, u.ProjectId)
				}
			}
		} else {
			//团队没查到也读用户自己配置
			for _, u := range user.SystemUserRestriction {
				userProjects = append(userProjects, u.ProjectId)
			}
		}
	}

	//团队取交集,再从团队权限取可见项目并累加
	var teamProjects []string
	if projectType == "team" {
		var userProjectList []string
		for _, u := range user.SystemUserRestriction {
			userProjectList = append(userProjectList, u.ProjectId)
		}
		//取交集
		for _, u := range userProjects {
			for _, t := range userProjectList {
				if u == t {
					teamProjects = append(teamProjects, u)
				}
			}
		}

		//查询无需权限也能看到的项目,累加到项目ID中
		var projectService services.CommonService[SystemProject]
		projectService.Page = 1
		projectService.PageSize = -1
		projectService.WhereStr = append(projectService.WhereStr, fmt.Sprintf("status = 1  and offline_date_time >= '%s' and visibility = 0 and project_id IN ('%s') ", time.Now().Format(utils.ServerConf.TimeLayoutStr), strings.Join(userProjects, "','")))
		if projectList, err := projectService.SelectList(); err != nil {
			ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
			return
		} else {
			if len(projectList.Data) > 0 {
				for _, u := range projectList.Data {
					teamProjects = append(teamProjects, u.ProjectId)
				}
			}
		}
	}

	/*//团队权限查询
	var teamProjects []string
	var teamDao dao2.Common[dao2.SystemTeam]
	isContinue := false
	//用户是团长则直接查团队配置
	if teamInfo, err := teamDao.First(map[string]interface{}{"user_id": claims.UserName, "status": 1}); err == nil {
		if utils.StringIsNotEmpty(teamInfo.TeamPermissions) {
			projectIds := strings.Split(teamInfo.TeamPermissions, "，")
			for _, id := range projectIds {
				teamProjects = append(teamProjects, id)
			}
		} else {
			isContinue = true
		}
	} else {
		//用户是团队也查询团队配置
		if utils.StringIsNotEmpty(user.TeamNumber) && user.TeamNumber != "zxz" {
			if teamInfo2, err := teamDao.First(map[string]interface{}{"team_number": user.TeamNumber, "status": 1}); err == nil {
				if utils.StringIsNotEmpty(teamInfo2.TeamPermissions) {
					projectIds := strings.Split(teamInfo2.TeamPermissions, "，")
					for _, id := range projectIds {
						teamProjects = append(teamProjects, id)
					}
				} else {
					isContinue = true
				}
			} else {
				ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"count": 0, "list": ""}})
				return
			}
		} else {
			ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"count": 0, "list": ""}})
			return
		}
	}

	var userProjects []string
	if !isContinue {
		//用户权限查询
		var userProjectLists []string
		for _, u := range user.SystemUserRestriction {
			userProjectLists = append(userProjectLists, u.ProjectId)
		}

		if len(teamProjects) > 0 && len(userProjectLists) > 0 {
			//取交集
			for _, u := range userProjectLists {
				for _, t := range teamProjects {
					if u == t {
						userProjects = append(userProjects, u)
					}
				}
			}
		} else {
			//用户或者团队权限有一个为空则无法取交集,返回空
			ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"count": 0, "list": ""}})
			return
		}

		//交集为空也无权限
		if len(userProjects) == 0 {
			ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"count": 0, "list": ""}})
			return
		}
	} else {
		for _, u := range user.SystemUserRestriction {
			userProjects = append(userProjects, u.ProjectId)
		}
	}

	//查询无需权限也能看到的项目,累加到项目ID中
	var projectService services.CommonService[SystemProject]
	projectService.Page = 1
	projectService.PageSize = -1
	projectService.WhereStr = append(projectService.WhereStr, fmt.Sprintf("status =1  and offline_date_time >= '%s' and visibility = 0 ", time.Now().Format(utils.ServerConf.TimeLayoutStr)))
	if projectList, err := projectService.SelectList(); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		if len(projectList.Data) > 0 {
			for _, u := range projectList.Data {
				userProjects = append(userProjects, u.ProjectId)
			}
		}
	}*/

	type SystemProject struct {
		ProjectId  string `json:"project_id"`
		Title      string `json:"title"`
		Id         string `json:"id"`
		Cover      string `json:"cover"`
		UserStatus int    `json:"user_status"`
		Status     int    `json:"status"`
		Category   string `json:"category"` //分类
		//CountdownAnswer int64  `json:"countdown_answer"` //答题倒计时，时长
		HasUnreadMessage             bool   `json:"hasUnreadMessage"`
		UnreadMessageCount           int64  `json:"unreadMessageCount"`
		ProjectPrice                 string `json:"project_price"`
		SpecialClassificationOne     string `json:"special_classification_one"` //特殊分类1(0-关闭,1-开启)
		SpecialClassificationOneName string `json:"special_classification_one_name"`
		SpecialClassificationTwo     string `json:"special_classification_two"` //特殊分类2(0-关闭,1-开启)
		SpecialClassificationTwoName string `json:"special_classification_two_name"`
		Collect                      string `json:"collect"` //收藏
	}
	var service services.CommonService[SystemProject]
	service.Page = RequestParams.Page
	service.PageSize = RequestParams.PageSize
	if RequestParams.Category != "" {
		service.Query = map[string]interface{}{"category": RequestParams.Category}
	}
	if RequestParams.SearchText != "" {
		service.WhereStr = append(service.WhereStr, fmt.Sprintf("project_id LIKE '%%%v%%' OR title LIKE '%%%v%%'", RequestParams.SearchText, RequestParams.SearchText))
	}
	if RequestParams.SpecialClassificationOne != "" {
		service.Query = map[string]interface{}{"special_classification_one": RequestParams.SpecialClassificationOne}
	}
	if RequestParams.SpecialClassificationTwo != "" {
		service.Query = map[string]interface{}{"special_classification_two": RequestParams.SpecialClassificationTwo}
	}
	if RequestParams.Collect != "" {
		userProjectCollect := make(map[string]interface{})
		exists, err := Redis.RedisGClient.Exists(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Result()
		if err != nil {
			return
		}
		if exists == 1 {
			jsonStr := Redis.RedisGClient.Get(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Val()
			err := json.Unmarshal([]byte(jsonStr), &userProjectCollect)
			if err != nil {
				fmt.Println("Error unmarshalling JSON:", err)
				return
			}
			collectProjects := ""
			if len(userProjectCollect) > 0 {
				for key := range userProjectCollect {
					collectProjects += "'" + key + "',"
				}
				collectProjects = collectProjects[:len(collectProjects)-1]
				service.WhereStr = append(service.WhereStr, fmt.Sprintf("project_id in (%s)", collectProjects))
			} else {
				ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"count": 0, "list": nil}})
				return
			}
		}
	}
	//查询自己有有权限的项目 + 项目设置了可见性的项目列表
	//service.WhereStr = append(service.WhereStr, fmt.Sprintf("status =1  and (offline_date_time >= '%s' and project_id IN ('%s') or visibility = 0) ",
	if projectType == "noTeam" {
		service.WhereStr = append(service.WhereStr, fmt.Sprintf("status =1  and offline_date_time >= '%s' and (project_id IN ('%s') or visibility = 0) ",
			time.Now().Format(utils.ServerConf.TimeLayoutStr),
			strings.Join(userProjects, "','")))
	} else {
		service.WhereStr = append(service.WhereStr, fmt.Sprintf("status =1  and offline_date_time >= '%s' and project_id IN ('%s')",
			time.Now().Format(utils.ServerConf.TimeLayoutStr),
			strings.Join(teamProjects, "','")))
	}
	/*
		//过滤项目状态已下线的去掉
		service.WhereStr = append(service.WhereStr, fmt.Sprintf("status =1"))
		//添加项目上线时间和结束时间的过滤
		//service.WhereStr = append(service.WhereStr, fmt.Sprintf("online_date_time <= '%s'", time.Now().Format(utils.ServerConf.TimeLayoutStr)))
		service.WhereStr = append(service.WhereStr, fmt.Sprintf("offline_date_time >= '%s'", time.Now().Format(utils.ServerConf.TimeLayoutStr)))

	*/
	service.Order = "sort,id"
	if res, err := service.SelectList(); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		//收藏赋值
		exists, err := Redis.RedisGClient.Exists(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Result()
		if err != nil {
			return
		}
		for i, project := range res.Data {
			if arrays.ContainsString(userProjects, project.ProjectId) > -1 {
				res.Data[i].UserStatus = 1
			}
			//查询用户未读消息
			var userMessageServe services.UserMessageService
			//if hasUnreadMessage, unreadMessageCount, err := userMessageServe.CheckUserProjectHasUnreadMessage(claims.Id, project.ProjectId); err != nil {
			if hasUnreadMessage, unreadMessageCount, err := userMessageServe.CheckUserProjectHasUnreadMessageNew2(user, project.ProjectId); err != nil {
				ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: "读取用户未读消息失败"})
				return
			} else {
				res.Data[i].HasUnreadMessage = hasUnreadMessage
				res.Data[i].UnreadMessageCount = unreadMessageCount
			}
			//特殊分类中文名赋值
			if res.Data[i].SpecialClassificationOne == "1" {
				res.Data[i].SpecialClassificationOneName = Redis.RedisGClient.Get("SpecialClassification_1").Val()
			}
			if res.Data[i].SpecialClassificationTwo == "1" {
				res.Data[i].SpecialClassificationTwoName = Redis.RedisGClient.Get("SpecialClassification_2").Val()
			}
			//收藏赋值
			if exists == 1 {
				userProjectCollect := make(map[string]interface{})
				jsonStr := Redis.RedisGClient.Get(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Val()
				err := json.Unmarshal([]byte(jsonStr), &userProjectCollect)
				if err != nil {
					fmt.Println("Error unmarshalling JSON:", err)
					return
				}
				if err != nil {
					fmt.Println("Error marshalling map to JSON:", err)
					return
				}
				if len(userProjectCollect) > 0 {
					for key := range userProjectCollect {
						if res.Data[i].ProjectId == key {
							res.Data[i].Collect = "1"
						}
					}
				}
			}
		}
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"count": res.Total, "list": res.Data}})
		return
	}

}

type ProjectDetailRequest struct {
	Id          uint   `json:"id" validate:"required"`
	TopicNumber int    `json:"topic_number"` // 领取数量
	TsTime      int    `json:"ts_time"`      // 题目开始时间，左端点（时间戳，单位：秒，下同）
	TeTime      int    `json:"te_time"`      // 题目开始时间，右端点
	TdsTime     int    `json:"tds_time"`     // 题目完成时间，左端点
	TdeTime     int    `json:"tde_time"`     // 题目完成时间，右端点
	TopicId     string `json:"topic_id"`     // 题目ID
	TeacherId   string `json:"teacher_id"`   // 领取老师ID
	TeamNumber  string `json:"team_number"`  // 团队编号
	Labels      string `json:"labels"`       // 搜索标签，多个标签分号隔开
	TopicName   string `json:"topic_name"`   // 搜索题目名称
}

// @Summary 项目详情
// @Description 项目详情
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /app/project/{id} [get]
func ProjectDetailHandler(ctx iris.Context) {
	var RequestParams ProjectDetailRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	//查询当前项目的详情
	var projectDao dao.Common[dao.SystemProject]
	projectDao.Query = map[string]interface{}{"id": RequestParams.Id}
	if project, err := projectDao.First(projectDao.Query); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		var claims services.CustomClaims
		if err := claims.ParseClaims(ctx); err != nil {
			ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
			return
		}
		var topicServe services.CommonService[dao.SystemTopic]
		topicServe.Query = map[string]interface{}{"project_id": project.ProjectId, "receiver_id": claims.UserName, "status": []int{2, 3}}
		topicServe.PageSize = -1
		topicServe.Order = "sn asc"
		if res, err := topicServe.SelectList(); err != nil {
			ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
			return
		} else {
			//收藏赋值
			exists, err := Redis.RedisGClient.Exists(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Result()
			if err != nil {
				return
			}
			//收藏赋值
			if exists == 1 {
				userProjectCollect := make(map[string]interface{})
				jsonStr := Redis.RedisGClient.Get(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Val()
				err := json.Unmarshal([]byte(jsonStr), &userProjectCollect)
				if err != nil {
					fmt.Println("Error unmarshalling JSON:", err)
					return
				}
				if err != nil {
					fmt.Println("Error marshalling map to JSON:", err)
					return
				}
				if len(userProjectCollect) > 0 {
					for key := range userProjectCollect {
						if project.ProjectId == key {
							project.Collect = "1"
						}
					}
				}
			}

			if res.Total == 0 {
				var topicsv services.TopicService
				takeNum := topicsv.GetTodayTakeNum(project.ProjectId, claims.UserName)
				giveUpNum := topicsv.GetTodayGiveUpNum(project.ProjectId, claims.UserName)
				topicLabels := topicsv.GetRemainTopicLabelNum(project.ProjectId)

				topicServe.WhereStr = []string{}
				topicServe.Query = map[string]interface{}{"project_id": project.ProjectId}
				//如果是一审项目,查询时则排除答主处理中的题目
				if project.EnumType == modelbase.AuditProj {
					topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("topic_id in (select topic_id from tas_system_topic WHERE project_id = '%v' and `status` = 1 )", project.WorkProjectId))
				} else if project.EnumType == modelbase.FinalProj {
					//如果是二审项目,查询时排除一审处理中的题目和答主处理中的题目
					topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("topic_id in (select topic_id from tas_system_topic WHERE project_id = '%v' and `status` = 1 and audit_status = 1 )", project.AuditProjectId))
					topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("topic_id in (select topic_id from tas_system_topic WHERE project_id = '%v' and `status` = 1 )", project.WorkProjectId))
				}
				topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("receiver_id = \"\" OR receiver_id IS NULL"))
				//topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("end_date_time > '%s'", time.Now().Format(timehandler.FormatLayoutTime)))
				topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("status = 5"))
				if RequestParams.TsTime > 0 && RequestParams.TeTime > 0 {
					topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("effective_time >= %v and effective_time <= %v", RequestParams.TsTime, RequestParams.TeTime))
				}
				if utils.StringIsNotEmpty(RequestParams.TopicId) {
					topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("topic_id = '%v'", RequestParams.TopicId))
				}
				//topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("(status = 0 and effective_time < '%s') OR (status = 5)", time.Now().Format(utils.ServerConf.TimeLayoutStr)))

				if lastCount, err := topicServe.Count(); err != nil {
					ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
					return
				} else {
					var user_restriction dao.Common[dao.SystemUserRestriction]
					user_restriction.Query = map[string]interface{}{"system_user_id": claims.Id, "project_id": project.ProjectId}
					restriction, _ := user_restriction.First(user_restriction.Query)

					//ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"take_count": takeNum, "give_up_count": giveUpNum, "topic_labels": topicLabels, "project_detail": project, "last_count": lastCount, "limit": restriction.Limit, "lower_limit": restriction.LowerLimit, "countdown_answer": project.CountdownAnswer}})
					ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"take_count": takeNum, "give_up_count": giveUpNum, "topic_labels": topicLabels, "project_detail": project, "last_count": lastCount, "day_limit": restriction.DayLimit, "day_give_up_limit": restriction.DayGiveUpLimit, "countdown_answer": project.CountdownAnswer}})
					return
				}
			} else {
				// 答主视角：无作答内容
				if project.EnumType == modelbase.WorkProj {
					ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"project_detail": project, "topic_list": res.Data}})
					return
				}
				// 1审视角：查询原题以及作答内容
				if project.EnumType == modelbase.AuditProj {
					topicVOList := batchQueryTopicAnswerVO(project.WorkProjectId, res.Data)
					ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"project_detail": project, "topic_list": topicVOList, "topic_audit_one_list": res.Data}})
					return
				}
				// 2审视角,查询原题/1审以及作答内容
				if project.EnumType == modelbase.FinalProj {
					//查询原题,用WorkProjectId查
					topicVOList := batchQueryTopicAnswerVO(project.WorkProjectId, res.Data)
					//查询一审题,用AuditProjectId查
					topicVOoneList := batchQueryTopicAnswerVO(project.AuditProjectId, res.Data)
					ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"project_detail": project, "topic_list": topicVOList, "topic_audit_one_list": topicVOoneList, "topic_audit_two_list": res.Data}})
				}
			}
		}
	}
}

// 查询原题和作答
func batchQueryTopicAnswerVO(projectId string, auditTopics []dao.SystemTopic) []dao.SystemTopicVO {
	topicIds := make([]string, 0)
	for _, topic := range auditTopics {
		topicIds = append(topicIds, topic.TopicId)
	}
	// 查询原题
	var topicServe services.CommonService[dao.SystemTopic]
	topicServe.Query = map[string]interface{}{"project_id": projectId, "topic_id": topicIds}
	res, err := topicServe.SelectList()
	if err != nil {
		// 降级处理
		return nil
	}
	topicList := res.Data
	// 查询答主信息
	usermap := batchTopicAuditUser(topicList)
	// 查询答主作答
	answermap := batchQueryTopicAnswer(topicList)
	// 组装返回数据
	voList := make([]dao.SystemTopicVO, 0)
	for _, topic := range topicList {
		topicVO := new(dao.SystemTopicVO)
		if err := utils.CopyProperties(&topic, topicVO); err != nil {
			glog.Errorf("RepairTopicHandler copy properties err: %v", err)
			continue
		}
		// 题目作答
		topicVO.TopicAnswer = dao.TopicAnswerVO{
			Respondent:    usermap[topic.ReceiverId],
			TopicAnswer:   answermap[topic.Id],
			FinishTime:    topic.FinishTime,
			RejectionRate: 0, // 驳回率
		}
		voList = append(voList, *topicVO)
	}
	return voList
}

type SystemProject struct {
	Banner     string `json:"banner"`
	Title      string `json:"title"`
	ProjectId  string `json:"project_id"`
	UserStatus int    `json:"user_status"`
	Id         uint   `json:"id"`
}

// @Summary Banner
// @Description Banner
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /app/project/index [get]
func ProjectIndexHandler(ctx iris.Context) {

	var result struct {
		HomeNotice string          `json:"home_notice"`
		Banners    []SystemProject `json:"banners"`
	}

	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	var common dao.Common[dao.HomeNotice]
	if res, err := common.First(map[string]interface{}{"status": 1}); err != nil {
		switch err {
		case gorm.ErrRecordNotFound:
			result.HomeNotice = ""
		default:
			ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
			return
		}
	} else {
		result.HomeNotice = res.Content
	}

	var commonuser dao.Common[dao.SystemUser]
	commonuser.Query = map[string]interface{}{"id": claims.Id}
	user, err := commonuser.First(commonuser.Query)
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}

	var userProjects []string
	for _, u := range user.SystemUserRestriction {
		userProjects = append(userProjects, u.ProjectId)
	}

	var projectServe services.CommonService[SystemProject]
	projectServe.Query = map[string]interface{}{"status": 1}
	projectServe.WhereStr = append(projectServe.WhereStr, fmt.Sprintf("banner != \"\""))
	projectServe.Order = "slide_show_sort"
	field := fmt.Sprintf("banner,title,project_id,id")
	projectServe.SelectField = &field
	if res, err := projectServe.SelectList(); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		for i, project := range res.Data {
			if arrays.ContainsString(userProjects, project.ProjectId) > -1 {
				res.Data[i].UserStatus = 1
			}
		}
		result.Banners = res.Data
	}
	ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: result})
	return
}

type GetTopicRequest struct {
	ProjectId    string `json:"project_id"`    // 项目ID
	TopicNumber  int    `json:"topic_number"`  // 领取数量
	TsTime       int    `json:"ts_time"`       // 题目开始时间，左端点（时间戳，单位：秒，下同）
	TeTime       int    `json:"te_time"`       // 题目开始时间，右端点
	TdsTime      int    `json:"tds_time"`      // 题目完成时间，左端点
	TdeTime      int    `json:"tde_time"`      // 题目完成时间，右端点
	TopicId      string `json:"topic_id"`      // 题目ID
	RespondentId string `json:"respondent_id"` // 答题人ID
	TeacherId    string `json:"teacher_id"`    // 领取老师ID
	TeamNumber   string `json:"team_number"`   // 团队编号
	Labels       string `json:"labels"`        // 搜索标签，多个标签分号隔开
	TopicName    string `json:"topic_name"`    // 搜索题目名称
}

// @Summary 领取题目
// @Description 领取题目
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param param body GetTopicRequest true "领取题目参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /app/project/get_topic [post]
func GetTopicHandler(ctx iris.Context) {
	var RequestParams GetTopicRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	glog.Infof("用户%s,领取项目id为%s,题目编号：%s", claims.UserName, RequestParams.ProjectId, RequestParams.TopicNumber)
	var topicServe services.TopicService
	if err := topicServe.GetTopic(RequestParams.TopicNumber, RequestParams.ProjectId, RequestParams.TopicId, RequestParams.TopicName, RequestParams.Labels, RequestParams.RespondentId, RequestParams.TeacherId, RequestParams.TeamNumber, int64(RequestParams.TsTime), int64(RequestParams.TeTime), int64(RequestParams.TdsTime), int64(RequestParams.TdeTime), claims.UserName, claims.Id); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.StatusText(iris.StatusOK)})
		return
	}
}

// @Summary 项目分类
// @Description 项目分类
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /app/project/category [get]
func ProjectCategoryHandler(ctx iris.Context) {

	var category services.ProjectService

	if res, err := category.GetCategoryList(); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: res})
		return
	}
}

type MessageListRequest struct {
	Page      int64  `json:"page"`
	PageSize  int64  `json:"page_size"`
	ProjectId string `json:"project_id"`
}

// @Summary 项目任务消息
// @Description 项目任务消息列表
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param param body MessageListRequest true "项目任务消息参数"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /app/project/message/list [post]
func ProjectMessageListHandler(ctx iris.Context) {
	var RequestParams MessageListRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	var projectServe services.ProjectService
	count, result := projectServe.MessageList(RequestParams.Page, RequestParams.PageSize, RequestParams.ProjectId, claims.Id)
	ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: iris.Map{"count": count, "list": result}})
	return
}

// @Summary 项目角标
// @Description 项目角标
// @Tags 项目
// @Accept application/json
// @Produce application/json
// @param Accept-Version header string true "1.0.0"
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @param id path uint true "项目Id"
// @Success 200 {object} utils.Response --> 成功后返回数据结构
// @Failure 400 {object} utils.ResponseError --> 失败后返回数据结构
// @Router /app/project/badge/{id} [get]
func BadgeHandler(ctx iris.Context) {
	projectId := ctx.Params().GetString("project_id")

	var result struct {
		Repair  int64 `json:"repair"`
		Message int64 `json:"message"`
	}

	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}

	var topicServe services.CommonService[dao.SystemTopic]
	topicServe.Query = map[string]interface{}{"project_id": projectId, "receiver_id": claims.UserName, "status": 4, "have_read": 0}
	topicServe.WhereStr = append(topicServe.WhereStr, fmt.Sprintf("finish_time > now() "))
	res, err := topicServe.Count()
	result.Repair = res
	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}

	var messageDao services2.CommonService[dao2.UserMsgInfo]
	var userDao dao.Common[dao.SystemUser]
	if user, err := userDao.First(map[string]interface{}{"id": claims.Id}); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		messageDao.LeftJoin = append(messageDao.LeftJoin, fmt.Sprintf("left join tas_system_msg m on tas_user_msg_info.msg_id = m.id"))
		messageDao.WhereStr = append(messageDao.WhereStr, fmt.Sprintf("tas_user_msg_info.system_user_id = '%v'", user.UserId))
		messageDao.WhereStr = append(messageDao.WhereStr, fmt.Sprintf("tas_user_msg_info.status = 0"))
		messageDao.WhereStr = append(messageDao.WhereStr, fmt.Sprintf("m.permissions = '%v'", projectId))
		if list, err := messageDao.FindWithLeftJoinAll(); err != nil {
			ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
			return
		} else {
			if len(list) == 0 {
				result.Message = 0
			} else {
				result.Message = int64(len(list))
			}
		}
	}
	/*var userMessageServe services.CommonService[dao.UserMessage]
	userMessageServe.Query = map[string]interface{}{"project_id": projectId, "system_user_id": claims.Id, "status": 0}
	if result.Message, err = userMessageServe.Count(); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}*/
	ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: result})
	return
}

type UpdateProjectMsgStatusRequest struct {
	ProjectId string `json:"project_id" validate:"required"`
}

func UpdateProjectMsgStatusHandler(ctx iris.Context) {
	var RequestParams MessageListRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}

	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}

	var messageServ services2.CommonService[dao2.UserMsgInfo]
	var userDao dao.Common[dao.SystemUser]
	if user, err := userDao.First(map[string]interface{}{"id": claims.Id}); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	} else {
		messageServ.LeftJoin = append(messageServ.LeftJoin, fmt.Sprintf("left join tas_system_msg m on tas_user_msg_info.msg_id = m.id"))
		messageServ.WhereStr = append(messageServ.WhereStr, fmt.Sprintf("tas_user_msg_info.system_user_id = '%v'", user.UserId))
		messageServ.WhereStr = append(messageServ.WhereStr, fmt.Sprintf("tas_user_msg_info.status = 0"))
		messageServ.WhereStr = append(messageServ.WhereStr, fmt.Sprintf("m.permissions = '%v'", RequestParams.ProjectId))
		if list, err := messageServ.FindWithLeftJoinAll(); err != nil {
			ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
			return
		} else {
			if len(list) > 0 {
				var canDelIds []uint
				for _, msgInfo := range list {
					canDelIds = append(canDelIds, msgInfo.Id)
				}
				var messageDao dao.Common[dao2.UserMsgInfo]
				if err := messageDao.BatchUpdate(canDelIds, map[string]interface{}{"status": 1}).Error; err != nil {
					ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
					return
				} else {
					ctx.JSON(utils.ResponseOK())
					return
				}
			}
		}
	}

}

type UserProjectAddCollectRequest struct {
	ProjectId string `json:"project_id" validate:"required"`
}

func UserProjectAddCollectHandler(ctx iris.Context) {
	var RequestParams UserProjectAddCollectRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}

	userProjectCollect := make(map[string]interface{})
	exists, err := Redis.RedisGClient.Exists(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Result()
	if err != nil {
		return
	}
	if exists == 1 {
		jsonStr := Redis.RedisGClient.Get(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Val()
		err := json.Unmarshal([]byte(jsonStr), &userProjectCollect)
		if err != nil {
			fmt.Println("Error unmarshalling JSON:", err)
			return
		}
		projectId := RequestParams.ProjectId
		userProjectCollect[projectId] = projectId
		jsonData, err := json.Marshal(userProjectCollect)
		if err != nil {
			fmt.Println("Error marshalling map to JSON:", err)
			return
		}
		Redis.RedisGClient.Set(fmt.Sprintf("UserProjectCollect_%d", claims.Id), jsonData, 0)
	} else {
		projectId := RequestParams.ProjectId
		userProjectCollect[projectId] = projectId
		jsonData, err := json.Marshal(userProjectCollect)
		if err != nil {
			fmt.Println("Error marshalling map to JSON:", err)
			return
		}
		Redis.RedisGClient.Set(fmt.Sprintf("UserProjectCollect_%d", claims.Id), jsonData, 0)
	}

	ctx.JSON(utils.ResponseOK())
	return
}

func UserProjectDelCollectHandler(ctx iris.Context) {
	var RequestParams UserProjectAddCollectRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var claims services.CustomClaims
	if err := claims.ParseClaims(ctx); err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}

	userProjectCollect := make(map[string]interface{})
	exists, err := Redis.RedisGClient.Exists(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Result()
	if err != nil {
		return
	}
	if exists == 1 {
		jsonStr := Redis.RedisGClient.Get(fmt.Sprintf("UserProjectCollect_%d", claims.Id)).Val()
		err := json.Unmarshal([]byte(jsonStr), &userProjectCollect)
		if err != nil {
			fmt.Println("Error unmarshalling JSON:", err)
			return
		}
		projectId := RequestParams.ProjectId
		delete(userProjectCollect, projectId)
		jsonData, err := json.Marshal(userProjectCollect)
		if err != nil {
			fmt.Println("Error marshalling map to JSON:", err)
			return
		}
		Redis.RedisGClient.Set(fmt.Sprintf("UserProjectCollect_%d", claims.Id), jsonData, 0)
	}

	ctx.JSON(utils.ResponseOK())
	return
}
